package interfacepackage

import (
	"fmt"
	"reflect"
	"sort"
	"strconv"
)

type test1Shaper interface {
	Area() float32
}

type test1Square struct {
	side float32
}

type test1Circle struct {
	r float32
}

func (sq test1Square) Area() float32 {
	return sq.side * sq.side
}

func (cr test1Circle) Area() float32 {
	return 3.14 * cr.r * cr.r
}

func test1() {
	sq := test1Square{10}
	cr := test1Circle{5}

	var areaInterface test1Shaper
	areaInterface = sq

	fmt.Println(areaInterface.Area())

	areaInterface = cr
	fmt.Println(areaInterface.Area())
}

type test2S struct {
	name  string
	score int
}

type TsArray []test2S

func (ts TsArray) Len() int {
	return len(ts)
}

func (ts TsArray) Less(i, j int) bool {
	return ts[i].score < ts[j].score
}

func (ts TsArray) Swap(i, j int) {
	ts[i], ts[j] = ts[j], ts[i]
}

func test2() {
	data := []test2S{{"jack", 80}, {"keven", 90}, {"joe", 70}}
	fmt.Println("排序前: ", data)
	//sort.Sort(data) 错误的调用，因为Sort的接收值是一个interface变量，所以要通过data创建出它对应的interface变量
	sort.Sort(TsArray(data))
	fmt.Println("排序后: ", data)
}

func test3() {
	testFunc := func(any interface{}) {
		switch v := any.(type) {
		case bool:
			fmt.Println("bool type", v)
		case int:
			fmt.Println("int type", v)
		case string:
			fmt.Println("string type", v)
		default:
			fmt.Println("other type", v)
		}
	}
	testFunc(1)
	testFunc(1.2)
	testFunc("hello world")
}

type node struct {
	next *node
	prev *node
	data interface{}
}

func test4() {
	root := &node{nil, nil, "hello root"}
	root.next = &node{nil, root, 10}
	root.prev = &node{root, nil, 20}

	fmt.Println(root.prev.data, root.data, root.next.data)
}

type test5S struct {
	firstname string
	lastname  string
}

func (ts *test5S) print2() {
	fmt.Println(ts.firstname, ts.lastname)
}

type test5PrintInterface interface {
	print1()
}

type test5MyInterface interface {
	print2()
}

func t5func(x test5MyInterface) {
	if p, ok := x.(test5PrintInterface); ok {
		p.print1()
	} else {
		fmt.Println("error")
	}
}

func test5() {
	ts := &test5S{"bob", "joe"}
	t5func(ts)
}

func test6() {
	var f float64
	v := reflect.ValueOf(f)
	fmt.Println(v)
	k := v.Kind()
	fmt.Println(k)
	fmt.Println(reflect.Float64)
}

func test7() {
	var x float64 = 2.3
	v := reflect.ValueOf(x)
	fmt.Println("can be set?", v.CanSet())
}

func test8() {
	var x float64 = 2.3
	v := reflect.ValueOf(&x)
	fmt.Println("can be set?", v.CanSet())
}

func test9() {
	var x float64 = 2.3
	v := reflect.ValueOf(&x)
	v = v.Elem()
	fmt.Println("can be set?", v.CanSet())
	v.SetFloat(20.1)
	fmt.Println(v)
	fmt.Println(x)
	fmt.Println(v.Interface())
}

type test10S1 struct {
	S1, s2, s3 string
}

type test10S2 struct {
	S1, s2 string
	i1     int
}

func (ts test10S1) String() string {
	return ts.S1 + "->" + ts.s2 + "->" + ts.s3
}

func (ts test10S2) String() string {
	return ts.S1 + "->" + ts.s2 + "->" + strconv.Itoa(ts.i1)
}

func test10Func(s1 interface{}) {
	typ := reflect.TypeOf(s1)
	val := reflect.ValueOf(s1)
	knd := val.Kind()
	fmt.Println(typ, val, knd)

	for i := 0; i < val.NumField(); i++ {
		fmt.Println(i, val.Field(i))
	}
}

func test10() {
	var s1 interface{} = test10S1{"hello", "go", "s1"}
	var s2 interface{} = test10S2{"hello", "hello", 10}
	ts := test10S1{"hello", "go", "s1"}
	reflect.ValueOf(&ts).Elem().Field(0).SetString("hee")
	test10Func(s1)
	test10Func(s2)
}

func Test() {
	test10()
}
